﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Dapper.Moon
{
    public abstract class QueryableProvide<T> : IQueryable<T>
    {
        #region
        protected IDatabase Database;
        protected IExpression ExpressionProvideObj;
        protected SqlBuilderResult __Where;
        protected MapperTable MasterTable = null;
        protected string MasterTableName;
        protected List<string> TableNames;
        protected List<MapperTable> JoinTables;
        protected string SelectColumns;
        protected int? Offset;
        protected int? Limit;
        protected bool IsHaveTotal = true;
        protected string __OrderBy;
        protected string GroupByField;
        protected SqlBuilderResult __Having;
        protected string FunctionSql;
        protected SqlBuilderResult Function;
        protected List<SqlBuilderResult> Joins;
        protected MapperTable SelectIntoTable;
        protected string IntoTableColumn;
        protected bool IsDistinct;
        protected bool IsRowLock = false;
        protected bool IsQuote = true;
        #endregion

        public QueryableProvide(IDatabase _Database)
        {
            Database = _Database;

            MapperTable classMapperT = ClassMapper.Mapping<T>();
            MasterTable = classMapperT;
            MasterTableName = Database.SqlDialect.SetSqlName(classMapperT.TableName);
            TableNames = new List<string>();
            JoinTables = new List<MapperTable>();

            ExpressionProvideObj = new ExpressionProvide(Database.SqlDialect, classMapperT);
        }

        #region
        public IQueryable<T> TableName(string tableName = null, bool isQuote = true)
        {
            IsQuote = isQuote;
            if (!string.IsNullOrWhiteSpace(tableName))
            {
                MasterTableName = IsQuote ? Database.SqlDialect.SetSqlName(tableName) : tableName;
            }
            return this;
        }

        protected void TableName(int index, string tableName)
        {
            if (!string.IsNullOrWhiteSpace(tableName))
            {
                TableNames[index] = IsQuote ? Database.SqlDialect.SetSqlName(tableName) : tableName;
            }
        }

        protected void TableName()
        {
            if (JoinTables?.Count > 0)
            {
                //移除第1张表
                JoinTables.RemoveAt(0);
                foreach (var item in JoinTables)
                {
                    TableNames.Add(IsQuote ? Database.SqlDialect.SetSqlName(item.TableName) : item.TableName);
                }
            }
        }

        protected void _Where(Expression where, bool isPrefix = false)
        {
            var ep = ExpressionProvideObj.ExpressionRouter(where, isPrefix);
            if (__Where == null)
            {
                __Where = ep;
                __Where.Sql = string.Concat("where ", ep.Sql);
            }
            else
            {
                __Where.Sql = string.Concat("where ", ep.Sql);
                if (ep.DynamicParameters.ParameterNames.Count() > 0)
                {
                    __Where.DynamicParameters.AddDynamicParams(ep.DynamicParameters);
                }
            }
        }

        protected void _Where(string where, object dynamic = null)
        {
            if (!string.IsNullOrWhiteSpace(where))
            {
                if (__Where == null)
                {
                    __Where = new SqlBuilderResult()
                    {
                        Sql = string.Concat("where ", where),
                        DynamicParameters = new DynamicParameters()
                    };
                }
                else
                {
                    __Where.Sql = string.Concat("where ", where);
                }
                if (dynamic != null)
                {
                    var dp = CommonUtils.GetDynamicParameters(dynamic);
                    if (dp.ParameterNames.Count() > 0)
                    {
                        __Where.DynamicParameters.AddDynamicParams(dp);
                    }
                }
            }
        }

        protected SqlBuilderResult _GetById(object id)
        {
            var array = MasterTable.Properties.Where(i => i.IsPrimaryKey);
            if (array != null && array.Count() == 1)
            {
                PropertyMap propertyMap = array.FirstOrDefault();
                string sql = $"{ Database.SqlDialect.SetSqlName(propertyMap.ColumnName) } = {Database.SqlDialect.ParameterPrefix}id";
                _Where(sql, null);
                SqlBuilderResult result = ToSql();
                result.DynamicParameters.Add("id", id);
                return result;
            }
            else
            {
                throw new Exception("primary key is empty or has more than one primary key");
            }
        }

        public T First(object id)
        {
            SqlBuilderResult result = _GetById(id);
            return Database.QueryFirst<T>(result.Sql, result.DynamicParameters);
        }

        public async Task<T> FirstAsync(object id)
        {
            SqlBuilderResult result = _GetById(id);
            return await Database.QueryFirstAsync<T>(result.Sql, result.DynamicParameters);
        }

        public IQueryable<T> Where(string where, object dynamic = null)
        {
            _Where(where, dynamic);
            return this;
        }

        public IQueryable<T> Where(Expression<Func<T, bool>> where)
        {
            _Where(where);
            return this;
        }

        protected void _Count(Expression field, bool isPrefix = false)
        {
            CommonUtils.ExpressionCheck(field, true);
            Function = ExpressionProvideObj.ExpressionRouter(field, isPrefix);
            if (IsDistinct)
            {
                FunctionSql = $"count(distinct {Function.Sql})";
            }
            else
            {
                FunctionSql = $"count({Function.Sql})";
            }
        }

        protected void _Count(string field, bool isPrefix = false)
        {
            FunctionSql = $"count({field})";
        }

        public IQueryable<T> Count(Expression<Func<T, object>> field)
        {
            _Count(field, false);
            return this;
        }

        protected void _Sum(Expression field, bool isPrefix = false)
        {
            CommonUtils.ExpressionCheck(field, true);
            Function = ExpressionProvideObj.ExpressionRouter(field, isPrefix);
            FunctionSql = $"sum({Function.Sql})";
        }

        public IQueryable<T> Sum(Expression<Func<T, object>> field)
        {
            _Sum(field, false);
            return this;
        }

        protected void _Avg(Expression field, bool isPrefix = false)
        {
            CommonUtils.ExpressionCheck(field, true);
            Function = ExpressionProvideObj.ExpressionRouter(field, isPrefix);
            FunctionSql = $"avg({Function.Sql})";
        }

        public IQueryable<T> Avg(Expression<Func<T, object>> field)
        {
            _Avg(field, false);
            return this;
        }

        protected void _Max(Expression field, bool isPrefix = false)
        {
            CommonUtils.ExpressionCheck(field, true);
            Function = ExpressionProvideObj.ExpressionRouter(field, isPrefix);
            FunctionSql = $"max({Function.Sql})";
        }

        public IQueryable<T> Max(Expression<Func<T, object>> field)
        {
            _Max(field, false);
            return this;
        }

        protected void _Min(Expression field, bool isPrefix = false)
        {
            CommonUtils.ExpressionCheck(field, true);
            Function = ExpressionProvideObj.ExpressionRouter(field, isPrefix);
            FunctionSql = $"min({Function.Sql})";
        }

        public IQueryable<T> Min(Expression<Func<T, object>> field)
        {
            _Min(field, false);
            return this;
        }

        protected void _Take(int limit)
        {
            Limit = limit;
        }

        public IQueryable<T> Take(int limit)
        {
            _Take(limit);
            return this;
        }

        public QueryPageResult<TResult> ToPageList<TResult>(int offset, int limit, bool isHaveTotal = true)
        {
            IsHaveTotal = isHaveTotal;
            Offset = offset;
            Limit = limit;
            SqlBuilderResult result = ToSql();
            return Database.QueryPage<TResult>(result.Sql, result.DynamicParameters);
        }

        public async Task<QueryPageResult<TResult>> ToPageListAsync<TResult>(int offset, int limit, bool isHaveTotal = true)
        {
            IsHaveTotal = isHaveTotal;
            Offset = offset;
            Limit = limit;
            SqlBuilderResult result = ToSql();
            return await Database.QueryPageAsync<TResult>(result.Sql, result.DynamicParameters);
        }

        public List<T> ToList()
        {
            SqlBuilderResult result = ToSql();
            return Database.Query<T>(result.Sql, result.DynamicParameters);
        }

        public async Task<List<T>> ToListAsync()
        {
            SqlBuilderResult result = ToSql();
            return await Database.QueryAsync<T>(result.Sql, result.DynamicParameters);
        }

        public async Task<List<TResult>> ToListAsync<TResult>()
        {
            SqlBuilderResult result = ToSql();
            return await Database.QueryAsync<TResult>(result.Sql, result.DynamicParameters);
        }

        public List<TResult> ToList<TResult>()
        {
            SqlBuilderResult result = ToSql();
            return Database.Query<TResult>(result.Sql, result.DynamicParameters);
        }

        public T First()
        {
            Limit = 1;
            SqlBuilderResult result = ToSql();
            return Database.QueryFirst<T>(result.Sql, result.DynamicParameters);
        }

        public async Task<T> FirstAsync()
        {
            Limit = 1;
            SqlBuilderResult result = ToSql();
            return await Database.QueryFirstAsync<T>(result.Sql, result.DynamicParameters);
        }

        public TResult First<TResult>()
        {
            SqlBuilderResult result = null;
            if (string.IsNullOrWhiteSpace(FunctionSql))
            {
                Limit = 1;
                result = ToSql();
                return Database.QueryFirst<TResult>(result.Sql, result.DynamicParameters);
            }
            result = ToSql();
            return Database.ExecuteScalar<TResult>(result.Sql, result.DynamicParameters);
        }

        public async Task<TResult> FirstAsync<TResult>()
        {
            SqlBuilderResult result = null;
            if (string.IsNullOrWhiteSpace(FunctionSql))
            {
                Limit = 1;
                result = ToSql();
                return await Database.QueryFirstAsync<TResult>(result.Sql, result.DynamicParameters);
            }
            result = ToSql();
            return await Database.ExecuteScalarAsync<TResult>(result.Sql, result.DynamicParameters);
        }

        public DataTable ToDataTable()
        {
            SqlBuilderResult result = ToSql();
            return Database.Query(result.Sql, result.DynamicParameters);
        }

        public async Task<DataTable> ToDataTableAsync()
        {
            SqlBuilderResult result = ToSql();
            return await Database.QueryAsync(result.Sql, result.DynamicParameters);
        }

        protected void _OrderBy(Expression field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc, bool isPrefix = false)
        {
            var ep = ExpressionProvideObj.ExpressionRouter(field, isPrefix, isAlias: false);
            __OrderBy += "," + ep.Sql + " " + orderBy.ToString();
            if (ep.DynamicParameters.ParameterNames.Count() > 0)
            {
                __Where.DynamicParameters.AddDynamicParams(ep.DynamicParameters);
            }
            __OrderBy = __OrderBy.Trim(',');
        }

        public IQueryable<T> OrderBy(Expression<Func<T, object>> field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy);
            return this;
        }

        protected void _OrderBy(string field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            __OrderBy = field + " " + orderBy.ToString();
        }

        public IQueryable<T> OrderBy(string field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy);
            return this;
        }

        protected void _GroupBy(Expression field, bool isPrefix = false)
        {
            var ep = ExpressionProvideObj.ExpressionRouter(field, isPrefix, isAlias: false);
            GroupByField = ep.Sql;
            if (string.IsNullOrWhiteSpace(SelectColumns))
            {
                SelectColumns = GroupByField;
            }
            if (ep.DynamicParameters.ParameterNames.Count() > 0)
            {
                __Where.DynamicParameters.AddDynamicParams(ep.DynamicParameters);
            }
        }

        protected void _GroupBy(string field, bool isPrefix = false)
        {
            GroupByField = field;
            if (string.IsNullOrWhiteSpace(SelectColumns))
            {
                SelectColumns = GroupByField;
            }
        }

        public IQueryable<T> GroupBy(Expression<Func<T, object>> field)
        {
            _GroupBy(field);
            return this;
        }

        public IQueryable<T> GroupBy(string field)
        {
            _GroupBy(field);
            return this;
        }

        protected void _Having(Expression where, bool isPrefix = false)
        {
            __Having = ExpressionProvideObj.ExpressionRouter(where, isPrefix);
        }

        protected void _Having(string where, object dynamic = null)
        {
            if (!string.IsNullOrWhiteSpace(where))
            {
                __Having = new SqlBuilderResult()
                {
                    Sql = where
                };
                var dp = CommonUtils.GetDynamicParameters(dynamic);
                __Having.DynamicParameters = dp;
            }
        }

        public IQueryable<T> Having(Expression<Func<T, bool>> where)
        {
            _Having(where);
            return this;
        }

        public IQueryable<T> Having(string where, object dynamic = null)
        {
            _Having(where, dynamic);
            return this;
        }

        protected void _Select(string field)
        {
            SelectColumns = field;
        }

        protected void _Select(Expression field, bool isPrefix = false)
        {
            var ep = ExpressionProvideObj.ExpressionRouter(field, isPrefix);
            SelectColumns = ep.Sql;
            if (__Where == null)
            {
                __Where = new SqlBuilderResult();
                __Where.DynamicParameters = new DynamicParameters();
            }
            if (ep.DynamicParameters.ParameterNames.Count() > 0)
            {
                __Where.DynamicParameters.AddDynamicParams(ep.DynamicParameters);
            }
        }

        public IQueryable<T> Select(string field)
        {
            _Select(field);
            return this;
        }

        public IQueryable<T> Select(Expression<Func<T, object>> field)
        {
            _Select(field);
            return this;
        }

        #region 提供子查询方法
        public bool Any()
        {
            return true;
        }

        public bool NotAny()
        {
            return false;
        }

        public bool Contains(Expression<Func<T, object>> field)
        {
            CommonUtils.ExpressionCheck(field, true);
            return true;
        }

        public bool NotContains(Expression<Func<T, object>> field)
        {
            CommonUtils.ExpressionCheck(field, true);
            return false;
        }

        public TResult Select<TResult>(Expression<Func<T, object>> field)
        {
            return default(TResult);
        }
        #endregion 提供子查询方法

        protected void _Join(string join, object dynamic = null)
        {
            if (!string.IsNullOrWhiteSpace(join))
            {
                Joins = new List<SqlBuilderResult>();
                Joins.Add(new SqlBuilderResult()
                {
                    Sql = join,
                    DynamicParameters = CommonUtils.GetDynamicParameters(dynamic)
                });
            }
        }

        protected void _Join(string joinType, Expression join)
        {
            if (Joins == null)
            {
                Joins = new List<SqlBuilderResult>();
            }
            if (Joins.Count + 1 > TableNames.Count)
            {
                throw new Exception("table join error");
            }
            var eb = ExpressionProvideObj.ExpressionRouter(join, true);
            Joins.Add(eb);
            string asName = "t" + (Joins.Count + 1);
            string tableName = TableNames[Joins.Count - 1];
            eb.Sql = string.Concat($"{joinType} {tableName} {asName} on ", eb.Sql);
        }

        protected void _Distinct()
        {
            IsDistinct = true;
        }

        public IQueryable<T> Distinct()
        {
            _Distinct();
            return this;
        }

        public int Into<TTarget>(Expression<Func<TTarget, object>> field = null)
        {
            SelectIntoTable = ClassMapper.Mapping<TTarget>();
            ExpressionProvideObj.AppendMappingTable(SelectIntoTable);
            if (field != null)
            {
                IntoTableColumn = ExpressionProvideObj.ExpressionRouter(field).Sql;
            }
            SqlBuilderResult result = ToSql();
            return Database.Execute(result.Sql, result.DynamicParameters);
        }

        public int Into(string tableName, string columns)
        {
            if (string.IsNullOrWhiteSpace(tableName))
            {
                throw new Exception("the parameter is empty");
            }
            IntoTableColumn = columns;
            SelectIntoTable = new MapperTable() { TableName = tableName };
            SqlBuilderResult result = ToSql();
            return Database.Execute(result.Sql, result.DynamicParameters);
        }

        public async Task<int> IntoAsync<TTarget>(Expression<Func<TTarget, object>> field = null)
        {
            SelectIntoTable = ClassMapper.Mapping<TTarget>();
            ExpressionProvideObj.AppendMappingTable(SelectIntoTable);
            if (field != null)
            {
                IntoTableColumn = ExpressionProvideObj.ExpressionRouter(field).Sql;
            }
            SqlBuilderResult result = ToSql();
            return await Database.ExecuteAsync(result.Sql, result.DynamicParameters);
        }

        public IQueryable<T> RowLock()
        {
            IsRowLock = true;
            return this;
        }
        #endregion

        public abstract SqlBuilderResult ToSql();
    }

    #region T2-T6
    public abstract class QueryableProvide<T, T2> : QueryableProvide<T>, IQueryable<T, T2>
    {
        public QueryableProvide(IDatabase _Database)
            : base(_Database)
        {
            JoinTables = ClassMapper.Mapping(new Type[]
            { typeof(T), typeof(T2)});
            ExpressionProvideObj = new ExpressionProvide(Database.SqlDialect, JoinTables.ToArray());
            base.TableName();
        }

        public IQueryable<T, T2> TableName(string tableName = null, string tableName2 = null, bool isQuote = true)
        {
            this.IsQuote = isQuote;
            if (!string.IsNullOrWhiteSpace(tableName))
            {
                MasterTableName = IsQuote ? Database.SqlDialect.SetSqlName(tableName) : tableName;
            }
            TableName(0, tableName2);
            return this;
        }

        public IQueryable<T, T2> Where(Expression<Func<MoonFunc<T, T2>, bool>> where)
        {
            _Where(where, true);
            return this;
        }

        public new IQueryable<T, T2> Where(string where, object dynamic = null)
        {
            _Where(where, dynamic);
            return this;
        }

        public IQueryable<T, T2> Count(Expression<Func<MoonFunc<T, T2>, object>> field)
        {
            _Count(field, true);
            return this;
        }

        public IQueryable<T, T2> Sum(Expression<Func<MoonFunc<T, T2>, object>> field)
        {
            _Sum(field, true);
            return this;
        }

        public IQueryable<T, T2> Avg(Expression<Func<MoonFunc<T, T2>, object>> field)
        {
            _Avg(field, true);
            return this;
        }

        public IQueryable<T, T2> Max(Expression<Func<MoonFunc<T, T2>, object>> field)
        {
            _Max(field, true);
            return this;
        }

        public IQueryable<T, T2> Min(Expression<Func<MoonFunc<T, T2>, object>> field)
        {
            _Min(field, true);
            return this;
        }

        public IQueryable<T, T2> OrderBy(Expression<Func<MoonFunc<T, T2>, object>> field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy, true);
            return this;
        }

        public new IQueryable<T, T2> OrderBy(string field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy);
            return this;
        }

        public IQueryable<T, T2> GroupBy(Expression<Func<MoonFunc<T, T2>, object>> field)
        {
            _GroupBy(field, true);
            return this;
        }

        public new IQueryable<T, T2> GroupBy(string field)
        {
            _GroupBy(field);
            return this;
        }

        public IQueryable<T, T2> Having(Expression<Func<MoonFunc<T, T2>, bool>> where)
        {
            _Having(where);
            return this;
        }

        public new IQueryable<T, T2> Having(string where, object dynamic = null)
        {
            _Having(where);
            return this;
        }

        public IQueryable<T, T2> Select(Expression<Func<MoonFunc<T, T2>, object>> field)
        {
            _Select(field, true);
            return this;
        }

        public new IQueryable<T, T2> Select(string field)
        {
            _Select(field);
            return this;
        }

        public IQueryable<T, T2> LeftJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }

        public IQueryable<T, T2> LeftJoin(Expression<Func<MoonFunc<T, T2>, bool>> join)
        {
            _Join("left join", join);
            return this;
        }

        public IQueryable<T, T2> InnerJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }

        public IQueryable<T, T2> InnerJoin(Expression<Func<MoonFunc<T, T2>, bool>> join)
        {
            _Join("inner join", join);
            return this;
        }

        public new IQueryable<T, T2> Take(int limit)
        {
            _Take(limit);
            return this;
        }

        public new IQueryable<T, T2> Distinct()
        {
            _Distinct();
            return this;
        }
    }

    public abstract class QueryableProvide<T, T2, T3> : QueryableProvide<T>, IQueryable<T, T2, T3>
    {
        public QueryableProvide(IDatabase _Database)
            : base(_Database)
        {
            JoinTables = ClassMapper.Mapping(new Type[]
            { typeof(T), typeof(T2), typeof(T3)});
            ExpressionProvideObj = new ExpressionProvide(Database.SqlDialect, JoinTables.ToArray());
            base.TableName();
        }

        public IQueryable<T, T2, T3> TableName(string tableName = null, string tableName2 = null, string tableName3 = null, bool isQuote = true)
        {
            this.IsQuote = isQuote;
            if (!string.IsNullOrWhiteSpace(tableName))
            {
                MasterTableName = IsQuote ? Database.SqlDialect.SetSqlName(tableName) : tableName;
            }
            TableName(0, tableName2);
            TableName(1, tableName3);
            return this;
        }

        public new IQueryable<T, T2, T3> Select(string field)
        {
            _Select(field);
            return this;
        }

        public IQueryable<T, T2, T3> Where(Expression<Func<MoonFunc<T, T2, T3>, bool>> where)
        {
            _Where(where, true);
            return this;
        }

        public new IQueryable<T, T2, T3> Where(string where, object dynamic = null)
        {
            _Where(where, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3> Count(Expression<Func<MoonFunc<T, T2, T3>, object>> field)
        {
            _Count(field, true);
            return this;
        }

        public IQueryable<T, T2, T3> Sum(Expression<Func<MoonFunc<T, T2, T3>, object>> field)
        {
            _Sum(field, true);
            return this;
        }

        public IQueryable<T, T2, T3> Avg(Expression<Func<MoonFunc<T, T2, T3>, object>> field)
        {
            _Avg(field, true);
            return this;
        }

        public IQueryable<T, T2, T3> Max(Expression<Func<MoonFunc<T, T2, T3>, object>> field)
        {
            _Max(field, true);
            return this;
        }

        public IQueryable<T, T2, T3> Min(Expression<Func<MoonFunc<T, T2, T3>, object>> field)
        {
            _Min(field, true);
            return this;
        }

        public IQueryable<T, T2, T3> OrderBy(Expression<Func<MoonFunc<T, T2, T3>, object>> field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy, true);
            return this;
        }

        public new IQueryable<T, T2, T3> OrderBy(string field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy);
            return this;
        }

        public IQueryable<T, T2, T3> GroupBy(Expression<Func<MoonFunc<T, T2, T3>, object>> field)
        {
            _GroupBy(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3> GroupBy(string field)
        {
            _GroupBy(field);
            return this;
        }

        public IQueryable<T, T2, T3> Having(Expression<Func<MoonFunc<T, T2, T3>, bool>> where)
        {
            _Having(where);
            return this;
        }

        public new IQueryable<T, T2, T3> Having(string where, object dynamic = null)
        {
            _Having(where);
            return this;
        }

        public IQueryable<T, T2, T3> Select(Expression<Func<MoonFunc<T, T2, T3>, object>> field)
        {
            _Select(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3> Take(int limit)
        {
            _Take(limit);
            return this;
        }

        public new IQueryable<T, T2, T3> Distinct()
        {
            _Distinct();
            return this;
        }

        public IQueryable<T, T2, T3> LeftJoin(Expression<Func<MoonFunc<T, T2, T3>, bool>> join)
        {
            _Join("left join", join);
            return this;
        }

        public IQueryable<T, T2, T3> LeftJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3> InnerJoin(Expression<Func<MoonFunc<T, T2, T3>, bool>> join)
        {
            _Join("inner join", join);
            return this;
        }

        public IQueryable<T, T2, T3> InnerJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }
    }

    public abstract class QueryableProvide<T, T2, T3, T4> : QueryableProvide<T>, IQueryable<T, T2, T3, T4>
    {
        public QueryableProvide(IDatabase _Database)
            : base(_Database)
        {
            JoinTables = ClassMapper.Mapping(new Type[]
            { typeof(T), typeof(T2), typeof(T3), typeof(T4)});
            ExpressionProvideObj = new ExpressionProvide(Database.SqlDialect, JoinTables.ToArray());
            base.TableName();
        }

        public IQueryable<T, T2, T3, T4> TableName(string tableName = null, string tableName2 = null, string tableName3 = null, string tableName4 = null, bool isQuote = true)
        {
            this.IsQuote = isQuote;
            if (!string.IsNullOrWhiteSpace(tableName))
            {
                MasterTableName = IsQuote ? Database.SqlDialect.SetSqlName(tableName) : tableName;
            }
            TableName(0, tableName2);
            TableName(1, tableName3);
            TableName(2, tableName4);
            return this;
        }

        public new IQueryable<T, T2, T3, T4> Select(string field)
        {
            _Select(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4> Where(Expression<Func<MoonFunc<T, T2, T3, T4>, bool>> where)
        {
            _Where(where, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4> Where(string where, object dynamic = null)
        {
            _Where(where, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4> Count(Expression<Func<MoonFunc<T, T2, T3, T4>, object>> field)
        {
            _Count(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4> Sum(Expression<Func<MoonFunc<T, T2, T3, T4>, object>> field)
        {
            _Sum(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4> Avg(Expression<Func<MoonFunc<T, T2, T3, T4>, object>> field)
        {
            _Avg(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4> Max(Expression<Func<MoonFunc<T, T2, T3, T4>, object>> field)
        {
            _Max(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4> Min(Expression<Func<MoonFunc<T, T2, T3, T4>, object>> field)
        {
            _Min(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4> OrderBy(Expression<Func<MoonFunc<T, T2, T3, T4>, object>> field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4> OrderBy(string field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy);
            return this;
        }

        public IQueryable<T, T2, T3, T4> GroupBy(Expression<Func<MoonFunc<T, T2, T3, T4>, object>> field)
        {
            _GroupBy(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4> GroupBy(string field)
        {
            _GroupBy(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4> Having(Expression<Func<MoonFunc<T, T2, T3, T4>, bool>> where)
        {
            _Having(where);
            return this;
        }

        public new IQueryable<T, T2, T3, T4> Having(string where, object dynamic = null)
        {
            _Having(where);
            return this;
        }

        public IQueryable<T, T2, T3, T4> Select(Expression<Func<MoonFunc<T, T2, T3, T4>, object>> field)
        {
            _Select(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4> Take(int limit)
        {
            _Take(limit);
            return this;
        }

        public new IQueryable<T, T2, T3, T4> Distinct()
        {
            _Distinct();
            return this;
        }

        public IQueryable<T, T2, T3, T4> LeftJoin(Expression<Func<MoonFunc<T, T2, T3, T4>, bool>> join)
        {
            _Join("left join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4> LeftJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4> InnerJoin(Expression<Func<MoonFunc<T, T2, T3, T4>, bool>> join)
        {
            _Join("inner join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4> InnerJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }
    }

    public abstract class QueryableProvide<T, T2, T3, T4, T5> : QueryableProvide<T>, IQueryable<T, T2, T3, T4, T5>
    {
        public QueryableProvide(IDatabase _Database)
            : base(_Database)
        {
            JoinTables = ClassMapper.Mapping(new Type[]
            { typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5)});
            ExpressionProvideObj = new ExpressionProvide(Database.SqlDialect, JoinTables.ToArray());
            base.TableName();
        }

        public IQueryable<T, T2, T3, T4, T5> TableName(string tableName = null, string tableName2 = null, string tableName3 = null, string tableName4 = null, string tableName5 = null, bool isQuote = true)
        {
            this.IsQuote = isQuote;
            if (!string.IsNullOrWhiteSpace(tableName))
            {
                MasterTableName = IsQuote ? Database.SqlDialect.SetSqlName(tableName) : tableName;
            }
            TableName(0, tableName2);
            TableName(1, tableName3);
            TableName(2, tableName4);
            TableName(3, tableName5);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5> Select(string field)
        {
            _Select(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> Where(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, bool>> where)
        {
            _Where(where, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5> Where(string where, object dynamic = null)
        {
            _Where(where, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> Count(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, object>> field)
        {
            _Count(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> Sum(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, object>> field)
        {
            _Sum(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> Avg(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, object>> field)
        {
            _Avg(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> Max(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, object>> field)
        {
            _Max(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> Min(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, object>> field)
        {
            _Min(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> OrderBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, object>> field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5> OrderBy(string field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> GroupBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, object>> field)
        {
            _GroupBy(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5> GroupBy(string field)
        {
            _GroupBy(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> Having(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, bool>> where)
        {
            _Having(where);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5> Having(string where, object dynamic = null)
        {
            _Having(where);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> Select(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, object>> field)
        {
            _Select(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5> Take(int limit)
        {
            _Take(limit);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5> Distinct()
        {
            _Distinct();
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> LeftJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, bool>> join)
        {
            _Join("left join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> LeftJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> InnerJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5>, bool>> join)
        {
            _Join("inner join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5> InnerJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }
    }

    public abstract class QueryableProvide<T, T2, T3, T4, T5, T6> : QueryableProvide<T>, IQueryable<T, T2, T3, T4, T5, T6>
    {
        public QueryableProvide(IDatabase _Database)
            : base(_Database)
        {
            JoinTables = ClassMapper.Mapping(new Type[]
            { typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6)});
            ExpressionProvideObj = new ExpressionProvide(Database.SqlDialect, JoinTables.ToArray());
            base.TableName();
        }

        public IQueryable<T, T2, T3, T4, T5, T6> TableName(string tableName = null, string tableName2 = null, string tableName3 = null, string tableName4 = null, string tableName5 = null, string tableName6 = null, bool isQuote = true)
        {
            this.IsQuote = isQuote;
            if (!string.IsNullOrWhiteSpace(tableName))
            {
                MasterTableName = IsQuote ? Database.SqlDialect.SetSqlName(tableName) : tableName;
            }
            TableName(0, tableName2);
            TableName(1, tableName3);
            TableName(2, tableName4);
            TableName(3, tableName5);
            TableName(4, tableName6);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6> Select(string field)
        {
            _Select(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> Where(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, bool>> where)
        {
            _Where(where, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6> Where(string where, object dynamic = null)
        {
            _Where(where, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> Count(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, object>> field)
        {
            _Count(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> Sum(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, object>> field)
        {
            _Sum(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> Avg(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, object>> field)
        {
            _Avg(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> Max(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, object>> field)
        {
            _Max(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> Min(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, object>> field)
        {
            _Min(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> OrderBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, object>> field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6> OrderBy(string field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> GroupBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, object>> field)
        {
            _GroupBy(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6> GroupBy(string field)
        {
            _GroupBy(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> Having(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, bool>> where)
        {
            _Having(where);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6> Having(string where, object dynamic = null)
        {
            _Having(where);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> Select(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, object>> field)
        {
            _Select(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6> Take(int limit)
        {
            _Take(limit);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6> Distinct()
        {
            _Distinct();
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> LeftJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, bool>> join)
        {
            _Join("left join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> LeftJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> InnerJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6>, bool>> join)
        {
            _Join("inner join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6> InnerJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }
    }
    #endregion T2-T6

    #region T7-T10
    public abstract class QueryableProvide<T, T2, T3, T4, T5, T6, T7> : QueryableProvide<T>, IQueryable<T, T2, T3, T4, T5, T6, T7>
    {
        public QueryableProvide(IDatabase _Database)
            : base(_Database)
        {
            JoinTables = ClassMapper.Mapping(new Type[]
            { typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7)});
            ExpressionProvideObj = new ExpressionProvide(Database.SqlDialect, JoinTables.ToArray());
            base.TableName();
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> TableName(string tableName = null, string tableName2 = null, string tableName3 = null, string tableName4 = null, string tableName5 = null, string tableName6 = null, string tableName7 = null, bool isQuote = true)
        {
            this.IsQuote = isQuote;
            if (!string.IsNullOrWhiteSpace(tableName))
            {
                MasterTableName = IsQuote ? Database.SqlDialect.SetSqlName(tableName) : tableName;
            }
            TableName(0, tableName2);
            TableName(1, tableName3);
            TableName(2, tableName4);
            TableName(3, tableName5);
            TableName(4, tableName6);
            TableName(5, tableName7);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7> Select(string field)
        {
            _Select(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> Where(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, bool>> where)
        {
            _Where(where, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7> Where(string where, object dynamic = null)
        {
            _Where(where, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> Count(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, object>> field)
        {
            _Count(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> Sum(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, object>> field)
        {
            _Sum(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> Avg(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, object>> field)
        {
            _Avg(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> Max(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, object>> field)
        {
            _Max(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> Min(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, object>> field)
        {
            _Min(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> OrderBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, object>> field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7> OrderBy(string field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> GroupBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, object>> field)
        {
            _GroupBy(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7> GroupBy(string field)
        {
            _GroupBy(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> Having(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, bool>> where)
        {
            _Having(where);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7> Having(string where, object dynamic = null)
        {
            _Having(where);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> Select(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, object>> field)
        {
            _Select(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7> Take(int limit)
        {
            _Take(limit);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7> Distinct()
        {
            _Distinct();
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> LeftJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, bool>> join)
        {
            _Join("left join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> LeftJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> InnerJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7>, bool>> join)
        {
            _Join("inner join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7> InnerJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }
    }

    public abstract class QueryableProvide<T, T2, T3, T4, T5, T6, T7, T8> : QueryableProvide<T>, IQueryable<T, T2, T3, T4, T5, T6, T7, T8>
    {
        public QueryableProvide(IDatabase _Database)
            : base(_Database)
        {
            JoinTables = ClassMapper.Mapping(new Type[]
            { typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8)});
            ExpressionProvideObj = new ExpressionProvide(Database.SqlDialect, JoinTables.ToArray());
            base.TableName();
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> TableName(string tableName = null, string tableName2 = null, string tableName3 = null, string tableName4 = null, string tableName5 = null, string tableName6 = null, string tableName7 = null, string tableName8 = null, bool isQuote = true)
        {
            this.IsQuote = isQuote;
            if (!string.IsNullOrWhiteSpace(tableName))
            {
                MasterTableName = IsQuote ? Database.SqlDialect.SetSqlName(tableName) : tableName;
            }
            TableName(0, tableName2);
            TableName(1, tableName3);
            TableName(2, tableName4);
            TableName(3, tableName5);
            TableName(4, tableName6);
            TableName(5, tableName7);
            TableName(6, tableName8);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Select(string field)
        {
            _Select(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Where(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, bool>> where)
        {
            _Where(where, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Where(string where, object dynamic = null)
        {
            _Where(where, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Count(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, object>> field)
        {
            _Count(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Sum(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, object>> field)
        {
            _Sum(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Avg(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, object>> field)
        {
            _Avg(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Max(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, object>> field)
        {
            _Max(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Min(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, object>> field)
        {
            _Min(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> OrderBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, object>> field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8> OrderBy(string field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> GroupBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, object>> field)
        {
            _GroupBy(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8> GroupBy(string field)
        {
            _GroupBy(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Having(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, bool>> where)
        {
            _Having(where);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Having(string where, object dynamic = null)
        {
            _Having(where);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Select(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, object>> field)
        {
            _Select(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Take(int limit)
        {
            _Take(limit);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8> Distinct()
        {
            _Distinct();
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> LeftJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, bool>> join)
        {
            _Join("left join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> LeftJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> InnerJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8>, bool>> join)
        {
            _Join("inner join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8> InnerJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }
    }

    public abstract class QueryableProvide<T, T2, T3, T4, T5, T6, T7, T8, T9> : QueryableProvide<T>, IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9>
    {
        public QueryableProvide(IDatabase _Database)
            : base(_Database)
        {
            JoinTables = ClassMapper.Mapping(new Type[]
            { typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9)});
            ExpressionProvideObj = new ExpressionProvide(Database.SqlDialect, JoinTables.ToArray());
            base.TableName();
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> TableName(string tableName = null, string tableName2 = null, string tableName3 = null, string tableName4 = null, string tableName5 = null, string tableName6 = null, string tableName7 = null, string tableName8 = null, string tableName9 = null, bool isQuote = true)
        {
            this.IsQuote = isQuote;
            if (!string.IsNullOrWhiteSpace(tableName))
            {
                MasterTableName = IsQuote ? Database.SqlDialect.SetSqlName(tableName) : tableName;
            }
            TableName(0, tableName2);
            TableName(1, tableName3);
            TableName(2, tableName4);
            TableName(3, tableName5);
            TableName(4, tableName6);
            TableName(5, tableName7);
            TableName(6, tableName8);
            TableName(7, tableName9);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Select(string field)
        {
            _Select(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Where(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, bool>> where)
        {
            _Where(where, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Where(string where, object dynamic = null)
        {
            _Where(where, dynamic);
            return this;
        }


        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Count(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, object>> field)
        {
            _Count(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Sum(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, object>> field)
        {
            _Sum(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Avg(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, object>> field)
        {
            _Avg(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Max(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, object>> field)
        {
            _Max(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Min(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, object>> field)
        {
            _Min(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> OrderBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, object>> field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> OrderBy(string field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> GroupBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, object>> field)
        {
            _GroupBy(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> GroupBy(string field)
        {
            _GroupBy(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Having(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, bool>> where)
        {
            _Having(where);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Having(string where, object dynamic = null)
        {
            _Having(where);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Select(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, object>> field)
        {
            _Select(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Take(int limit)
        {
            _Take(limit);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> Distinct()
        {
            _Distinct();
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> LeftJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, bool>> join)
        {
            _Join("left join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> LeftJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> InnerJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9>, bool>> join)
        {
            _Join("inner join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9> InnerJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }
    }

    public abstract class QueryableProvide<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> : QueryableProvide<T>, IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>
    {
        public QueryableProvide(IDatabase _Database)
            : base(_Database)
        {
            JoinTables = ClassMapper.Mapping(new Type[]
            { typeof(T), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10)});
            ExpressionProvideObj = new ExpressionProvide(Database.SqlDialect, JoinTables.ToArray());
            base.TableName();
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> TableName(string tableName = null, string tableName2 = null, string tableName3 = null, string tableName4 = null, string tableName5 = null, string tableName6 = null, string tableName7 = null, string tableName8 = null, string tableName9 = null, string tableName10 = null, bool isQuote = true)
        {
            this.IsQuote = isQuote;
            if (!string.IsNullOrWhiteSpace(tableName))
            {
                MasterTableName = IsQuote ? Database.SqlDialect.SetSqlName(tableName) : tableName;
            }
            TableName(0, tableName2);
            TableName(1, tableName3);
            TableName(2, tableName4);
            TableName(3, tableName5);
            TableName(4, tableName6);
            TableName(5, tableName7);
            TableName(6, tableName8);
            TableName(7, tableName9);
            TableName(8, tableName10);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Select(string field)
        {
            _Select(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Where(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, bool>> where)
        {
            _Where(where, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Where(string where, object dynamic = null)
        {
            _Where(where, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Count(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, object>> field)
        {
            _Count(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Sum(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, object>> field)
        {
            _Sum(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Avg(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, object>> field)
        {
            _Avg(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Max(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, object>> field)
        {
            _Max(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Min(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, object>> field)
        {
            _Min(field, true);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> OrderBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, object>> field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> OrderBy(string field, OrderBy orderBy = Dapper.Moon.OrderBy.Asc)
        {
            _OrderBy(field, orderBy);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> GroupBy(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, object>> field)
        {
            _GroupBy(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> GroupBy(string field)
        {
            _GroupBy(field);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Having(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, bool>> where)
        {
            _Having(where);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Having(string where, object dynamic = null)
        {
            _Having(where);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Select(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, object>> field)
        {
            _Select(field, true);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Take(int limit)
        {
            _Take(limit);
            return this;
        }

        public new IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> Distinct()
        {
            _Distinct();
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> LeftJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, bool>> join)
        {
            _Join("left join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> LeftJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> InnerJoin(Expression<Func<MoonFunc<T, T2, T3, T4, T5, T6, T7, T8, T9, T10>, bool>> join)
        {
            _Join("inner join", join);
            return this;
        }

        public IQueryable<T, T2, T3, T4, T5, T6, T7, T8, T9, T10> InnerJoin(string join, object dynamic = null)
        {
            _Join(join, dynamic);
            return this;
        }
    }
    #endregion T7-T10
}
